﻿//-----------------------------------------------------------------------
// <Copyright>
// * Copyright (C) 2022 RuYiAdmin All Rights Reserved
// </Copyright>
//-----------------------------------------------------------------------

using RuYiAdmin.Net.CommonInfrastructure.Configurations;
using RuYiAdmin.Net.CommonInfrastructure.Constants.Framework;
using RuYiAdmin.Net.CommonInfrastructure.Models;
using RuYiAdmin.Net.EntityDataModel.DataTransformationModel.SystemModel;
using RuYiAdmin.Net.EntityDataModel.EntityModel.SystemModel;
using RuYiAdmin.Net.RepositoryLayer.DataRepository.Interface.FrameworkInterface;
using RuYiAdmin.Net.RepositoryLayer.DataRepository.Interface.SystemInterface;
using RuYiAdmin.Net.ServiceLayer.BaseService.Implementation;
using RuYiAdmin.Net.ServiceLayer.BusinessService.Interface.SystemInterface;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RuYiAdmin.Net.ServiceLayer.BusinessService.Implementation.SystemImplementation
{
    /// <summary>
    /// 菜单业务层实现
    /// </summary>
    class SysMenuService : RuYiAdminBaseService<SysMenu>, ISysMenuService
    {
        #region 属性及构造函数

        /// <summary>
        /// 菜单仓储实例
        /// </summary>
        private readonly ISysMenuRepository MenuRepository;

        /// <summary>
        /// Redis仓储实例
        /// </summary>
        private readonly IRedisRepository RedisRepository;

        /// <summary>
        /// 业务日志仓储接口实例
        /// </summary>
        private readonly ILoggerRepository LoggerRepository;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="MenuRepository"></param>
        /// <param name="RedisRepository"></param>
        /// <param name="LoggerRepository"></param>
        public SysMenuService(ISysMenuRepository MenuRepository,
                              IRedisRepository RedisRepository,
                              ILoggerRepository LoggerRepository) : base(MenuRepository)
        {
            this.MenuRepository = MenuRepository;
            this.RedisRepository = RedisRepository;
            this.LoggerRepository = LoggerRepository;
        }

        #endregion

        #region 服务层公有方法

        #region 获取菜单树

        /// <summary>
        /// 获取菜单树
        /// </summary>
        /// <returns>ActionResponseResult</returns>
        public async Task<QueryResponseResult<SysMenuDTO>> GetMenuTreeNodes()
        {
            var result = new List<SysMenuDTO>();

            var menus = await this.RedisRepository.GetAsync<List<SysMenuDTO>>(RuYiGlobalConfig.SystemCacheConfig.MenuCacheName);
            var parentMenus = menus.Where(t => t.ParentId == null).OrderBy(t => t.SerialNumber).ToList();
            foreach (var item in parentMenus)
            {
                GetNodeChildren(item, menus);
            }
            result.AddRange(parentMenus);

            return QueryResponseResult<SysMenuDTO>.Success(result);
        }

        #endregion

        #region 加载系统菜单缓存

        /// <summary>
        /// 加载系统菜单缓存
        /// </summary>
        public async Task LoadSystemMenuCache()
        {
            int totalCount = 0;
            var rootList = (await this.MenuRepository.DefaultSqlQueryAsync<SysMenuDTO>(new SearchCondition(), totalCount)).ToList();
            await this.RedisRepository.SetAsync(RuYiGlobalConfig.SystemCacheConfig.MenuCacheName, rootList, -1);

            this.LoggerRepository.Info("系统菜单缓存加载完成");
        }

        #endregion

        #region 清理系统菜单缓存

        /// <summary>
        /// 清理系统菜单缓存
        /// </summary>
        public async Task ClearSystemMenuCache()
        {
            await this.RedisRepository.DeleteAsync(new string[] { RuYiGlobalConfig.SystemCacheConfig.MenuCacheName });

            this.LoggerRepository.Info("系统菜单缓存清理完成");
        }

        #endregion

        #endregion

        #region 服务层私有方法

        /// <summary>
        /// 递归树
        /// </summary>
        /// <param name="root">根节点</param>
        /// <param name="menus">菜单列表</param>
        private void GetNodeChildren(SysMenuDTO root, List<SysMenuDTO> menus)
        {
            var languages = this.RedisRepository.Get<List<SysLanguage>>(RuYiGlobalConfig.SystemCacheConfig.LanguageCacheName);

            var lanEn = languages.Where(t => t.LanguageName.Equals(Keywords.LANGUAGE_EN)).FirstOrDefault();
            var lanRu = languages.Where(t => t.LanguageName.Equals(Keywords.LANGUAGE_RU)).FirstOrDefault();

            var menuLanguages = this.RedisRepository.Get<List<SysMenuLanguage>>(RuYiGlobalConfig.SystemCacheConfig.MenuAndLanguageCacheName);

            #region 初始化多语

            var enMenu = menuLanguages.Where(t => t.MenuId.Equals(root.Id) && t.LanguageId.Equals(lanEn.Id)).FirstOrDefault();
            var ruMenu = menuLanguages.Where(t => t.MenuId.Equals(root.Id) && t.LanguageId.Equals(lanRu.Id)).FirstOrDefault();

            if (enMenu != null)
            {
                root.MenuNameEn = enMenu.MenuName;
            }

            if (ruMenu != null)
            {
                root.MenuNameRu = ruMenu.MenuName;
            }

            #endregion

            var list = menus.Where(t => t.ParentId == root.Id).ToList();
            if (list.Count > 0)
            {
                root.Children = new List<SysMenuDTO>();
                root.Children.AddRange(list.OrderBy(t => t.SerialNumber).ToList());

                foreach (var item in list)
                {
                    GetNodeChildren(item, menus);
                }
            }
        }

        #endregion
    }
}
